package com.cosc716.restaurant.domain;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;

import com.cosc716.restaurant.util.exception.InitializationException;

public class Menu {

	private ArrayList<MenuItem> menus = null;
	private String filepath;
	File filename;

	public Menu() {
		filepath = "resources/menu.txt";
		filename = new File(filepath);
		menus = this.getMenuItems();
	}

	public ArrayList<MenuItem> getMenuItems() {
		menus = new ArrayList<MenuItem>();
		try {
			this.checkfile();
			if (filename.exists()) {
				BufferedReader in = new BufferedReader(new FileReader(filename));
				String line = in.readLine();

				while (line != null) {
					String[] columns = line.split("\t");
					String name = columns[0];
					String price = columns[1];
					String ingredient = columns[2];
					String calories = columns[3];
					String rating = columns[4];
					String heartHealthy = columns[5];
					MenuItem p = new MenuItem(name, Double.parseDouble(price),
							ingredient, Double.parseDouble(calories),
							Double.parseDouble(rating),
							Boolean.parseBoolean(heartHealthy));
					menus.add(p);
					// System.out.println(p);
					line = in.readLine();

				}
			}
		} catch (IOException e) {
			System.out.println(e);
			return null;
		}

		return menus;
	}
public int getsize()
{
	return menus.size();
	}

public MenuItem getitem(int index)
{
	return menus.get(index);
	}
	public void checkfile() throws IOException {
		if (!filename.exists())
			filename.createNewFile();
	}

	public boolean additem(MenuItem item) {
		menus.add(item);
		try {
			PrintWriter out = new PrintWriter(new BufferedWriter(
					new FileWriter(filename, true)));
			out.println(item.getName() + "\t" + item.getPrice() + "\t"
					+ item.getIngredient() + "\t" + item.getCalories() + "\t"
					+ item.getRating());
			out.close();
			System.out.println(item.getName() + " Successfully added");
		} catch (IOException e) {
			System.out.println(e);
			return false;
		}
		return true;
	}

	public void deleteitem(MenuItem item) {
		menus.remove(item);
		try {
			PrintWriter out = new PrintWriter(new BufferedWriter(
					new FileWriter(filename)));
			for (MenuItem m : menus) {
				out.println(m.getName() + "\t" + m.getPrice() + "\t"
						+ m.getIngredient() + "\t" + m.getCalories() + "\t"
						+ m.getRating());

			}
			out.close();
		} catch (IOException e) {
			System.out.println(e);
		}

	}

	public MenuItem getitem(String name) {
		for (MenuItem m : menus) {
			if (m.getName().equalsIgnoreCase(name))
				return m;
		}

		return null;

	}

	public void saveitem() {

	}

	public String display() {
		String result = "";
		for (MenuItem m : menus)
			result += m;
		return result;
	}
	

	@Override
	public String toString() {
		return display();
	}

	private static MenuIterator getMenuIterator(Menu menu) {
		return new MenuIterator(menu);
	}

	public MenuIterator getMenuIterator() {
		return getMenuIterator(this);
	}

	private static MenuItemMenuIterator getMenuItemMenuIterator(Menu menu,
			MenuItem searchItem) {
		return new MenuItemMenuIterator(menu, searchItem);
	}

	public MenuItemMenuIterator getMenuItemMenuIterator(MenuItem searchItem) {
		return getMenuItemMenuIterator(this, searchItem);
	}

	private static HeartHealthyMenuIterator getHeartHealthyMenuIterator(
			Menu menu) {
		return new HeartHealthyMenuIterator(menu);
	}

	public HeartHealthyMenuIterator getHeartHealthyMenuIteratorMenuIterator() {
		return getHeartHealthyMenuIterator(this);
	}

	private static MaxPriceMenuIterator getMaxPriceMenuIterator(Menu menu,
			double maxPrice) throws InitializationException {
		return new MaxPriceMenuIterator(menu, maxPrice);
	}

	public MaxPriceMenuIterator getMaxPriceMenuIterator(double maxPrice)
			throws InitializationException {
		return getMaxPriceMenuIterator(this, maxPrice);
	}
}

class MenuIterator implements Iterator<MenuItem> {

	private ArrayList<MenuItem> menu = null;
	private int position = 0;

	public MenuIterator(Menu menu) {
		this.menu = menu.getMenuItems();
	}

	@Override
	public boolean hasNext() {
		while (position < menu.size()) {
			return true;
		}

		return false;
	}

	@Override
	public MenuItem next() {
		return menu.get(position++);
	}

	@Override
	public void remove() {
		menu.remove(position);
	}

}

class MenuItemMenuIterator implements Iterator<MenuItem> {

	private ArrayList<MenuItem> menu = null;
	private MenuItem searchItem = null;
	private int position = 0;

	public MenuItemMenuIterator(Menu menu, MenuItem searchItem) {
		this.menu = menu.getMenuItems();
		this.searchItem = searchItem;
	}

	@Override
	public boolean hasNext() {
		while (position < menu.size()) {
			if (menu.get(position).getName().equals(searchItem)) {
				return true;
			}
			position++;
		}

		return false;
	}

	@Override
	public MenuItem next() {
		return menu.get(position++);
	}

	@Override
	public void remove() {
		menu.remove(position);
	}

}

class HeartHealthyMenuIterator implements Iterator<MenuItem> {

	private ArrayList<MenuItem> menu = null;
	private int position = 0;

	public HeartHealthyMenuIterator(Menu menu) {
		this.menu = menu.getMenuItems();
	}

	@Override
	public boolean hasNext() {
		while (position < menu.size()) {
			if (menu.get(position).isHeartHealthy()) {
				return true;
			}
			position++;
		}

		return false;
	}

	@Override
	public MenuItem next() {
		return menu.get(position++);
	}

	@Override
	public void remove() {
		menu.remove(position);
	}

}

class MaxPriceMenuIterator implements Iterator<MenuItem> {

	private ArrayList<MenuItem> menu = null;
	private int position = 0;
	private double maxPrice = 0.0;

	public MaxPriceMenuIterator(Menu menu, double maxPrice)
			throws InitializationException {
		if (maxPrice < 0.0) {
			throw new InitializationException(
					"Maximum search price may not be less than 0");
		}

		this.menu = menu.getMenuItems();
		this.maxPrice = maxPrice;
	}

	@Override
	public boolean hasNext() {
		while (position < menu.size()) {
			if (menu.get(position).getPrice() <= maxPrice) {
				return true;
			}
			position++;
		}

		return false;
	}

	@Override
	public MenuItem next() {
		return menu.get(position++);
	}

	@Override
	public void remove() {
		menu.remove(position);
	}

	public double getMaxPrice() {
		return maxPrice;
	}

	public void setMaxPrice(double maxPrice) {
		this.maxPrice = maxPrice;
	}

}
